import os
from datetime import timedelta
from pathlib import Path
import sys

import environ
env = environ.Env()


from celery.schedules import crontab

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

print(f'BASE_DIR:{BASE_DIR}')
# APPS_DIR = os.path.join(Path(__file__).resolve().parent, 'apps')
# ['/Users/chao/Desktop/meiduo_24/meiduo_mall', '/Users/chao/Desktop/meiduo_24', '/Users/chao/.virtualenvs/meiduo/lib/python36.zip', '/Users/chao/.virtualenvs/meiduo/lib/python3.6', '/Users/chao/.virtualenvs/meiduo/lib/python3.6/lib-dynload', '/usr/local/Cellar/python3/3.6.2/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Users/chao/.virtualenvs/meiduo/lib/python3.6/site-packages', '/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend']
# 追加系统的导包路径(目的: 1.注册子应用时 可以写的方便点, 2.修改django认证模型类时,必须以 应用名.模型名)
# sys.path.insert(0, APPS_DIR)
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
sys.path.insert(0, os.path.join(BASE_DIR, 'zanhu'))

env.read_env(os.path.join(BASE_DIR, '.env'))

# SECURITY WARNING: keep the secret key used in production secret!
# SECRET_KEY = env('SECRET_KEY') #这种方式不能用特殊字符
SECRET_KEY = 'amtf-django-insecure-mlq6(#a^2vk!1=7=xhp#$i=o5d%namfs=+b26$m#sh_2rco7j^'


# 如果前端是代理，则可以通过该配置，在系统构建url的时候，获取正确的 scheme
# 需要在 前端加入该配置  proxy_set_header X-Forwarded-Proto https;
# https://docs.djangoproject.com/zh-hans/4.2/ref/settings/#std-setting-SECURE_PROXY_SSL_HEADER
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

# Application definition
DJANGO_APPS = [
    'daphne',  # 支持websocket
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # 赞乎
    # 'django.contrib.sites',
    # 'django.forms',  # 放在此列表的最后！用户后面重写django内置widget的模板
]
THIRD_PARTY_APPS = [
    'rest_framework_simplejwt',
    'rest_framework_simplejwt.token_blacklist',
    'captcha',
    'corsheaders',
    'rest_framework',
    'django_filters',
    'django_celery_results',
    'django_celery_beat',
    'imagekit',

    #赞乎
    # 'channels',
    # 'crispy_forms',
    # "crispy_bootstrap4",
    # 'sorl.thumbnail',
    # 'allauth',
    # 'allauth.account',
    # 'allauth.socialaccount',
    # 'allauth.socialaccount.providers.github',
    # 'django_comments',
    # 'markdownx',
    # 'taggit',
    # 'haystack',
    # 'djcelery_email',
]
LOCAL_APPS = [
    'common.apps.CommonConfig',
    'system.apps.SystemConfig',
    'message.apps.MessageConfig',
    'apps.users',

    # 'zanhu.users.apps.UsersConfig',
    # # # Your stuff: custom apps go here
    # 'zanhu.news.apps.NewsConfig',
    # 'zanhu.articles.apps.ArticlesConfig',
    # 'zanhu.qa.apps.QaConfig',
    # 'zanhu.messager.apps.MessagerConfig',
    # 'zanhu.notifications.apps.NotificationsConfig',
    # 'zanhu.search.apps.SearchConfig',
]
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',

    # 'allauth.account.middleware.AccountMiddleware',

    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'common.core.middleware.ApiLoggingMiddleware',
    'utils.middleware.AmtfMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
# TEMPLATES = [
#     {
#         # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
#         'BACKEND': 'django.template.backends.django.DjangoTemplates',
#         # https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
#         'DIRS': [
#             BASE_DIR / 'zanhu/templates'
#         ],
#         'OPTIONS': {
#             # https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
#             'debug': True,
#             # https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
#             # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
#             'loaders': [
#                 'django.template.loaders.filesystem.Loader',
#                 'django.template.loaders.app_directories.Loader',
#             ],
#             # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
#             'context_processors': [
#                 'django.template.context_processors.debug',
#                 'django.template.context_processors.request',  # django-allauth需要用到的
#                 'django.contrib.auth.context_processors.auth',
#                 'django.template.context_processors.i18n',
#                 'django.template.context_processors.media',
#                 'django.template.context_processors.static',
#                 'django.template.context_processors.tz',
#                 'django.contrib.messages.context_processors.messages',
#             ],
#         },
#     },
# ]


# WSGI_APPLICATION = 'server.wsgi.application'
ASGI_APPLICATION = "config.asgi.application"

# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

REDIS_PASSWORD = "nineven"
# REDIS_HOST = "redis"
REDIS_HOST = "127.0.0.1"
REDIS_PORT = 6379
DEFAULT_CACHE_ID = 1
CHANNEL_LAYERS_CACHE_ID = 2
CELERY_BROKER_CACHE_ID = 3
存储验证码id = 4
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": f"redis://{REDIS_HOST}:{REDIS_PORT}/{DEFAULT_CACHE_ID}",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 8000},
            "PASSWORD": REDIS_PASSWORD,
            "DECODE_RESPONSES": True
        },
        "TIMEOUT": 60 * 15,
        "KEY_FUNCTION": "common.base.utils.redis_key_func",
        "REVERSE_KEY_FUNCTION": "common.base.utils.redis_reverse_key_func",
    },
    "verify_codes": {  # 存储验证码
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": f"redis://{REDIS_HOST}:{REDIS_PORT}/{存储验证码id}",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}

# create database server default character set utf8 COLLATE utf8_general_ci;
# grant all on server.* to server@'127.0.0.1' identified by 'KGzKjZpWBp4R4RSa';
# python manage.py makemigrations
# python manage.py migrate
DATABASES = {
    # 'default': {
    #     'ENGINE': 'django.db.backends.mysql',
    #     'NAME': 'server',
    #     'USER': 'server',
    #     'PASSWORD': 'KGzKjZpWBp4R4RSa',
    #     'HOST': 'mariadb',
    #     'PORT': 3306,
    #     'CONN_MAX_AGE': 600,
    #     # 设置MySQL的驱动
    #     # 'OPTIONS': {'init_command': 'SET storage_engine=INNODB'},
    #     'OPTIONS': {'init_command': 'SET sql_mode="STRICT_TRANS_TABLES"', 'charset': 'utf8mb4'}
    # },
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}
# https://docs.djangoproject.com/zh-hans/5.0/topics/db/multi-db/#automatic-database-routing
# 读写分离 可能会出现 the current database router prevents this relation.
# 1.项目设置了router读写分离，且在ORM create()方法中，使用了前边filter()方法得到的数据，
# 2.由于django是惰性查询，前边的filter()并没有立即查询，而是在create()中引用了filter()的数据时，执行了filter()，
# 3.此时写操作的db指针指向write_db，filter()的db指针指向read_db，两者发生冲突，导致服务禁止了此次与mysql的交互
# 解决办法：
# 在前边filter()方法中，使用using()方法，使filter()方法立即与数据库交互，查出数据。
# Author.objects.using("default")
# >>> p = Person(name="Fred")
# >>> p.save(using="second")  # (statement 2)

DATABASE_ROUTERS = ['common.core.db.router.DBRouter']

CHANNEL_LAYERS = {
    "default": {
        # "BACKEND": "channels_redis.core.RedisChannelLayer",
        "BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
        "CONFIG": {
            "hosts": [f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}/{CHANNEL_LAYERS_CACHE_ID}"],
        },
    },
}

# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# 修改Django用户认证后端类
AUTHENTICATION_BACKENDS = ['apps.users.utils.UsernameMobileAuthBackend']

# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
AUTH_USER_MODEL = "system.UserInfo"

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = 'static/'

# Media配置
MEDIA_URL = "media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "upload")
FILE_UPLOAD_SIZE = 1024 * 1024 * 10
PICTURE_UPLOAD_SIZE = 1024 * 1024 * 0.5
FILE_UPLOAD_HANDLERS = [
    "django.core.files.uploadhandler.MemoryFileUploadHandler",
    "django.core.files.uploadhandler.TemporaryFileUploadHandler",
]

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'common.core.auth.CookieJWTAuthentication',
        # 'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'EXCEPTION_HANDLER': 'common.core.exception.common_exception_handler',
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {  # {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
        'anon': '60/m',
        'user': '600/m',
        'upload': '100/m',
        'download1': '10/m',
        'download2': '100/h',
        'register': '10/d',
    },
    'DEFAULT_PAGINATION_CLASS': 'common.core.pagination.PageNumber',
    'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.IsAuthenticated',
        'common.core.permission.IsAuthenticated',
    ],
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.OrderingFilter',
        'common.core.filter.DataPermissionFilter'
    ),
}

# DRF扩展缓存时间
REST_FRAMEWORK_EXTENSIONS = {
    # 缓存时间
    'DEFAULT_CACHE_RESPONSE_TIMEOUT': 3600,
    # 缓存存储
    'DEFAULT_USE_CACHE': 'default',
}

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(seconds=3600),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=15),
    'ROTATE_REFRESH_TOKENS': True,
    'BLACKLIST_AFTER_ROTATION': True,
    'UPDATE_LAST_LOGIN': True,  # 在登录的时候更新user表  last_login 字段

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUDIENCE': 'x',
    'ISSUER': 'server',
    'JWK_URL': None,
    'LEEWAY': 0,

    'AUTH_HEADER_TYPES': ('Bearer',),
    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',

    'AUTH_TOKEN_CLASSES': ('common.core.auth.ServerAccessToken',),
    # 'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',
    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}

CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = True

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'POST',
    'PUT',
)

CORS_ALLOW_HEADERS = (
    'XMLHttpRequest',
    "accept",
    "accept-encoding",
    "authorization",
    "content-type",
    "dnt",
    "origin",
    "user-agent",
    "x-csrftoken",
    "x-requested-with",
    "x-token"
)

LOG_DIR = os.path.join(BASE_DIR, "logs")
BASE_LOG_DIR = os.path.join(BASE_DIR, "logs", "api")
TMP_LOG_DIR = os.path.join(BASE_DIR, "logs", "tmp")
CELERY_LOG_DIR = os.path.join(BASE_DIR, "logs", "task")
if not os.path.isdir(BASE_LOG_DIR):
    os.makedirs(BASE_LOG_DIR)
if not os.path.isdir(TMP_LOG_DIR):
    os.makedirs(TMP_LOG_DIR)
if not os.path.isdir(CELERY_LOG_DIR):
    os.makedirs(CELERY_LOG_DIR)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '[%(filename)s:%(funcName)s:%(lineno)d %(levelname)s] %(asctime)s %(process)d %(thread)d %(message)s'
        },
        'main': {
            'datefmt': '%Y-%m-%d %H:%M:%S',
            'format': '%(asctime)s [%(filename)s:%(funcName)s:%(lineno)d %(levelname)s] %(message)s',
        },
        'exception': {
            'datefmt': '%Y-%m-%d %H:%M:%S',
            'format': '\n%(asctime)s [%(levelname)s] %(message)s',
        },
        'simple': {
            'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(funcName)s:%(lineno)d]%(message)s'
        },
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],  # 只有在Django debug为True时才在屏幕打印日志
            'class': 'logging.StreamHandler',
            'formatter': 'main'
        },
        'server': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件，根据时间自动切
            'filename': os.path.join(BASE_LOG_DIR, "server.log"),  # 日志文件
            'maxBytes': 1024 * 1024 * 100,  # 日志大小 100M
            'backupCount': 10,  # 备份数为3
            # 'when': 'W6',  # 每天一切， 可选值有S/秒 M/分 H/小时 D/天 W0-W6/周(0=周一) midnight/如果没指定时间就默认在午夜
            'formatter': 'main',
            'encoding': 'utf-8',
        },
        'drf_exception': {
            'encoding': 'utf8',
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',
            'formatter': 'exception',
            'maxBytes': 1024 * 1024 * 100,
            'backupCount': 7,
            'filename': os.path.join(BASE_LOG_DIR, "drf_exception.log"),
        },
        'unexpected_exception': {
            'encoding': 'utf8',
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',
            'formatter': 'exception',
            'maxBytes': 1024 * 1024 * 100,
            'backupCount': 7,
            'filename': os.path.join(BASE_LOG_DIR, "unexpected_exception.log"),
        },
        'sql': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件，自动切
            'filename': os.path.join(BASE_LOG_DIR, "sql.log"),  # 日志文件
            'maxBytes': 1024 * 1024 * 50,  # 日志大小 50M
            'backupCount': 10,
            'formatter': 'verbose',
            'encoding': 'utf-8',
        },
        'file': {  # 向文件中输出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            # 日志文件的位置
            'filename': os.path.join(LOG_DIR, "amtf.log"),
            'maxBytes': 100 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {
        '': {  # 默认的logger应用如下配置
            'handlers': ['server', 'console', 'drf_exception', 'unexpected_exception'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'django': {  # 定义了一个名为django的日志器
            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
        'django.request': {
            'handlers': ['console', 'server'],
            'level': 'DEBUG',
            'propagate': False,
        },
        'django.server': {
            'handlers': ['console', 'server'],
            'level': 'DEBUG',
            'propagate': False,
        },
        # 'django.db.backends': {
        #     # 'handlers': ['console', 'sql'],
        #     'handlers': ['console'],
        #     'propagate': True,
        #     'level': 'DEBUG',
        # },
        'drf_exception': {
            'handlers': ['console', 'drf_exception'],
            'level': 'ERROR',
        },
        'unexpected_exception': {
            'handlers': ['console', 'unexpected_exception'],
            'level': 'ERROR',
        },
    },
}

CACHE_KEY_TEMPLATE = {
    'config_key': 'config',
    'make_token_key': 'make_token',
    'download_url_key': 'download_url',
    'pending_state_key': 'pending_state',
    'upload_part_info_key': 'upload_part_info',
    'black_access_token_key': 'black_access_token',
}

# Celery Configuration Options
# https://docs.celeryq.dev/en/stable/userguide/configuration.html?
CELERY_TIMEZONE = "Asia/Shanghai"
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60

CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True

# CELERY_RESULT_BACKEND = ''
# CELERY_CACHE_BACKEND = 'django-cache'

CELERY_RESULT_BACKEND = 'django-db'
CELERY_CACHE_BACKEND = 'default'

# broker redis
DJANGO_DEFAULT_CACHES = CACHES['default']
CELERY_BROKER_URL = f'redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}/{CELERY_BROKER_CACHE_ID}'

# CELERY_WORKER_CONCURRENCY = 10  # worker并发数
# which needs two numbers: the maximum and minimum number of pool processes
CELERY_WORKER_AUTOSCALE = [10, 3]

CELERYD_FORCE_EXECV = True  # 非常重要,有些情况下可以防止死
CELERY_RESULT_EXPIRES = 3600 * 24 * 7  # 任务结果过期时间

# 任务发出后，经过一段时间还未收到acknowledge , 就将任务重新交给其他worker执行
CELERY_WORKER_DISABLE_RATE_LIMITS = True
CELERY_WORKER_PREFETCH_MULTIPLIER = 60  # celery worker 每次去redis取任务的数量

CELERY_WORKER_MAX_TASKS_PER_CHILD = 200  # 每个worker执行了多少任务就会死掉，我建议数量可以大一些，比如200

CELERY_ENABLE_UTC = False
DJANGO_CELERY_BEAT_TZ_AWARE = True

CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'

# celery消息的序列化方式，由于要把对象当做参数所以使用pickle
# CELERY_RESULT_SERIALIZER = 'pickle'
# CELERY_ACCEPT_CONTENT = ['pickle']
# CELERY_TASK_SERIALIZER = 'pickle'

CELERY_BEAT_SCHEDULE = {
    'auto_clean_operation_job': {
        'task': 'system.tasks.auto_clean_operation_job',
        'schedule': crontab(hour='2', minute='2'),
        'args': ()
    },
    'auto_clean_expired_captcha_job': {
        'task': 'system.tasks.auto_clean_expired_captcha_job',
        'schedule': crontab(hour='2', minute='12'),
        'args': ()
    },
    'auto_clean_black_token_job': {
        'task': 'system.tasks.auto_clean_black_token_job',
        'schedule': crontab(hour='2', minute='22'),
        'args': ()
    },
    'auto_clean_tmp_file_job': {
        'task': 'system.tasks.auto_clean_tmp_file_job',
        'schedule': crontab(hour='2', minute='32'),
        'args': ()
    }
}

# 字母验证码
CAPTCHA_IMAGE_SIZE = (120, 40)  # 设置 captcha 图片大小
CAPTCHA_LENGTH = 6  # 字符个数
CAPTCHA_TIMEOUT = 1  # 超时(minutes)

# 加减乘除验证码
CAPTCHA_OUTPUT_FORMAT = '%(image)s %(text_field)s %(hidden_field)s '
CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_null',
                           'captcha.helpers.noise_arcs',  # 线
                           'captcha.helpers.noise_dots',  # 点
                           )
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'

APPEND_SLASH = False

HTTP_BIND_HOST = '0.0.0.0'
HTTP_LISTEN_PORT = 8896
# celery flower 任务监控配置
CELERY_FLOWER_PORT = 5566
CELERY_FLOWER_HOST = '127.0.0.1'
CELERY_FLOWER_AUTH = 'flower:flower123.'

# 访问白名单配置
PERMISSION_WHITE_URL = [
    "^/api/system/login$",
    "^/api/system/logout$",
    "^/api/system/userinfo/self$",
    "^/api/system/notice/unread$",
    "^/api/system/routes$",
]

# 访问权限配置
PERMISSION_SHOW_PREFIX = [
    'api/system',
    'api/flower',
]
# 数据权限配置
PERMISSION_DATA_AUTH_APPS = [
    'system'
]

API_LOG_ENABLE = True
API_LOG_METHODS = ["POST", "DELETE", "PUT", "PATCH"]  # 'ALL'

# 在操作日志中详细记录的请求模块映射
API_MODEL_MAP = {
    "/api/system/refresh": "Token刷新",
    "/api/system/upload": "文件上传",
    "/api/system/login": "用户登录",
    "/api/system/logout": "用户登出",
    "/api/flower": "定时任务",
}

HAYSTACK_CONNECTIONS = {
    'default': {
        # 使用的Elasticsearch搜索引擎
        # 'ENGINE': 'haystack.backends.elasticsearch2_backend.Elasticsearch2SearchEngine',
        'ENGINE': 'haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine',
        # Elasticsearch连接的地址
        'URL': 'http://127.0.0.1:9200/',
        # 默认的索引名
        'INDEX_NAME': 'amtf',
    }
}

HAYSTACK_SEARCH_RESULTS_PER_PAGE = 20  # 分页
# 实时信号量处理器，模型类中数据增加、更新、删除时自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'